package com.gitee.swsk33;

import com.gitee.swsk33.util.PublicKeyUtils;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.shell.InteractiveProcessShellFactory;
import org.apache.sshd.server.shell.ProcessShellCommandFactory;
import org.apache.sshd.sftp.server.SftpSubsystemFactory;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

public class Main {

	public static void main(String[] args) throws Exception {
		// 假设从数据库获取的公钥
		String getKey = "ssh-rsa AAAAB3U... extra";
		// 创建一个ssh服务端对象
		SshServer sshd = SshServer.setUpDefaultServer();
		// 设定端口
		sshd.setPort(2333);
		// 设置服务端私钥路径
		// 私钥不存在会自动生成
		Path keyPath = Paths.get("hostkey");
		sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(keyPath));
		// 设置解释器工厂，当用户连接时需要启动服务器的交互式Shell，通常是执行bash或者fish等解释器
		sshd.setShellFactory(new InteractiveProcessShellFactory());
		// 设定命令工厂，设定后用户可通过SSH直接执行命令而非交互式执行
		sshd.setCommandFactory(new ProcessShellCommandFactory());
		// 设置认证方式，这里使用自定义实现的公钥认证
		sshd.setPublickeyAuthenticator((username, key, session) -> {
			// 这里编写认证公钥的逻辑，公钥对比成功则返回true
			System.out.println("用户名：" + username);
			// 获取会话信息
			System.out.println("用户远程地址：" + session.getClientAddress());
			// 获取和对比公钥内容
			String clientKeyPEM = PublicKeyUtils.publicKeyToBase64String(key);
			System.out.println("公钥：" + clientKeyPEM);
			String getKeyPEM = PublicKeyUtils.opensshPublicKeyToPEM(getKey);
			// 返回false表示认证失败，拒绝连接，true表示成功允许连接
			if (getKeyPEM.equals(clientKeyPEM)) {
				System.out.println("公钥一致！");
				return true;
			} else {
				System.out.println("公钥不一致！应该是：" + getKeyPEM);
				return false;
			}
		});
		// 设置sftp子系统
		sshd.setSubsystemFactories(List.of(new SftpSubsystemFactory()));
		// 启动服务端
		sshd.start();
		while (sshd.isStarted()) {
			// ...
		}
	}

}